package org.rcy.framework.file.pdf;

import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor;
import com.itextpdf.kernel.pdf.canvas.parser.PdfTextExtractor;
import com.itextpdf.kernel.pdf.canvas.parser.listener.IPdfTextLocation;
import com.itextpdf.kernel.pdf.canvas.parser.listener.RegexBasedLocationExtractionStrategy;
import com.itextpdf.kernel.pdf.tagutils.TagStructureContext;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class ReplaceUtils {

    public static void doOverText(OverTextDTO overTextDTO,InputStream is, OutputStream os) throws IOException {

        Map<String,String> keyMap = new HashMap<String, String>();
        PdfDocument pdfDocument = new PdfDocument(new PdfReader(is), new PdfWriter(os));
        //为key自动加上占位符并转义
        for(String key : overTextDTO.getReplaceMap().keySet()) {
            keyMap.put(key,"\\$\\<" + key + "\\>");
        }
        List<List<OverAreaDTO>> lists =
                getTextPosition(pdfDocument,keyMap,overTextDTO.getReplaceMap());

        overText(pdfDocument,lists,overTextDTO.getFont());
        pdfDocument.close();
    }

    /**
     * 获取关键字的坐标
     * @param keyMap
     * @return
     */
    private static  List<List<OverAreaDTO>> getTextPosition(   PdfDocument pdfDocument, Map<String,String> keyMap,Map<String,String> replaceMap) throws IOException {

        List<List<OverAreaDTO>> list = new ArrayList<List<OverAreaDTO>>();

        for (int i = 1; i <= pdfDocument.getNumberOfPages(); i++) {


            List<OverAreaDTO> overAreaDTOS = new ArrayList<OverAreaDTO>();

            for (String key  : keyMap.keySet()) {

                PdfPage page = pdfDocument.getPage(i);

                RegexBasedLocationExtractionStrategy strategy = new RegexBasedLocationExtractionStrategy(keyMap.get(key));
                PdfCanvasProcessor canvasProcessor = new PdfCanvasProcessor(strategy);
                canvasProcessor.processPageContent(page);
                Collection<IPdfTextLocation> resultantLocations = strategy.getResultantLocations();
                for (IPdfTextLocation location : resultantLocations) {
                    Rectangle rectangle = location.getRectangle();
                    OverAreaDTO overAreaDTO = new OverAreaDTO();
                    overAreaDTO.setPageNum(location.getPageNumber());
                    overAreaDTO.setX(rectangle.getX());
                    overAreaDTO.setY(rectangle.getY());
                    overAreaDTO.setWidth(rectangle.getWidth());
                    overAreaDTO.setHeight(rectangle.getHeight());
                    overAreaDTO.setKey(key);
                    overAreaDTO.setValue(replaceMap.get(key));
                    overAreaDTOS.add(overAreaDTO);
                }
            }

            list.add(overAreaDTOS);
        }
        return list;
    }

    /**
     * 覆盖原有的内容 并填充新内容
     *
     * @param list
     */
    private  static void overText(PdfDocument pdfDoc, List<List<OverAreaDTO>> list, PdfFont font) throws IOException {
        for (int i = 1; i <= pdfDoc.getNumberOfPages(); i++) {
            PdfCanvas canvas = new PdfCanvas(pdfDoc.getPage(i).newContentStreamAfter(),
                    pdfDoc.getPage(i).getResources(), pdfDoc);

            canvas.saveState();
            List<OverAreaDTO> overAreaDTOS = list.get(i-1);
            //用白色背景覆盖原本的字体
            for (OverAreaDTO overArea :overAreaDTOS) {
                canvas.setFillColor(ColorConstants.WHITE);
                //覆盖的时候y + 0.35   填充字体的时候 + 1.5 主要就是避免覆盖占位符下面的线
                canvas.rectangle(overArea.getX(), overArea.getY() + 0.35, overArea.getWidth(), overArea.getHeight());
            }
            canvas.fill();
            canvas.restoreState();

            //填充新内容
            canvas.beginText();
            for (OverAreaDTO overArea :overAreaDTOS) {
                canvas.setFontAndSize(font,overArea.getHeight());
                canvas.setTextMatrix(overArea.getX(),overArea.getY() + 1.5f);
                canvas.newlineShowText(overArea.getValue());
            }
            canvas.endText();
        }

        pdfDoc.close();

    }

    private float getPageMaxHeight(Rectangle rectangle){
        return rectangle.getHeight()*25.4f/72;
    }

    private float getPageMaxWith(Rectangle rectangle){
        return rectangle.getWidth()*25.4f/72;
    }

}
